package com.example.simple_android.controller.impl;

import android.annotation.SuppressLint;
import android.view.MotionEvent;
import android.view.View;

import com.example.simple_android.annotation.OnClick;
import com.example.simple_android.annotation.OnLongClick;
import com.example.simple_android.annotation.OnTouch;
import com.example.simple_android.controller.AbstractController;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ViewController extends AbstractController<View> {


    @Override
    public void initValue() {

    }

    @Override
    public void initElementClick() {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            OnClick onClick = field.getDeclaredAnnotation(OnClick.class);
            if (onClick == null) {
                continue;
            }
            String methodName = onClick.methodName();
            Method method;
            try {
                method = clazz.getDeclaredMethod(methodName, field.getType());
            } catch (NoSuchMethodException e) {
                continue;
            }
            field.setAccessible(true);
            try {
                Object o = field.get(this);
                if (o instanceof View) {
                    ((View) o).setOnClickListener((view) -> {
                        try {
                            method.setAccessible(true);
                            method.invoke(this);
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    });
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void initElementLongClick() {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            OnLongClick onLongClick = field.getDeclaredAnnotation(OnLongClick.class);
            if (onLongClick == null) {
                continue;
            }
            Method method;
            try {
                method = clazz.getDeclaredMethod(onLongClick.methodName(), field.getType());
            } catch (NoSuchMethodException e) {
                continue;
            }
            field.setAccessible(true);
            try {
                Object o = field.get(this);
                if (o instanceof View) {
                    ((View) o).setOnLongClickListener((view) -> {
                        boolean result = false;
                        try {
                            method.setAccessible(true);
                            Object invoke = method.invoke(this, view);
                            if (invoke instanceof Boolean) {
                                result = (boolean) invoke;
                            }
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            e.printStackTrace();
                        }
                        return result;
                    });
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public void initElementTouchClick() {
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            OnTouch onTouch = field.getDeclaredAnnotation(OnTouch.class);
            if (onTouch == null) {
                continue;
            }
            Method method;
            try {
                method = clazz.getDeclaredMethod(onTouch.methodName(), View.class, MotionEvent.class);
            } catch (NoSuchMethodException e) {
                continue;
            }
            field.setAccessible(true);
            try {
                Object o = field.get(this);
                if (o instanceof View) {
                    ((View) o).setOnTouchListener((v, event) -> {
                        boolean result = false;
                        method.setAccessible(true);
                        try {
                            Object invoke = method.invoke(this);
                            if (invoke instanceof Boolean) {
                                result = (boolean) invoke;
                            }
                        } catch (IllegalAccessException | InvocationTargetException e) {
                            e.printStackTrace();
                        }
                        return result;
                    });
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public <F> F findElement(int key) {
        return (F) target.findViewById(key);
    }
}
